import requests
import json
from flask import jsonify, request
from app.libs.error_code import Success, ApiTestFail, ApiTestSuccess
from app.libs.redprint import Redprint
from app.libs.token_auth import auth
from app.models.apis import Apis, Config, Scene, ApisScene, ApiExecutiveLogging
from app.models.base import db
from app.validators.apis import ApisForm, ConfigForm, SceneForm, ApisSceneForm, SceneScriptForm
import random
api = Redprint('apis')


@api.route('/config', methods=['POST'])
@auth.login_required
def config():
    form = ConfigForm().validate_for_api()
    Config.add_config(form.ip.data, form.ip_name.data)
    return Success()


@api.route('/config_use', methods=['POST'])
@auth.login_required
def config_use():
    id=request.json.get('id')
    Config.use_0(id)
    return Success()


@api.route('/examine_config', methods=['POST'])
@auth.login_required
def examine_config():
    configs=Config.query.filter_by().all()
    config = [config for config in configs]
    return jsonify(config)

@api.route('/update_config', methods=['POST'])
@auth.login_required
def update_config():
    id=request.json.get('id')
    config=Config.query.get(id)
    config.ip=request.json.get('ip')
    config.ip_name = request.json.get('ip_name')
    db.session.commit()
    return Success()


# 接口录入
@api.route('/api_record', methods=['POST'])
@auth.login_required
def api_record():
    form = ApisForm().validate_for_api()
    path = form.path.data
    data = form.parameter.data
    ip = Config.query.filter_by(use=1).first().ip
    headers = form.headers.data
    asserts = form.asserts_expression.data
    print(asserts)
    method = form.request_method.data
    a = http(path, data, ip, headers, method, asserts,form.api_name.data)
    print(a)
    print(headers)
    if a['ex_code'] == 0:
        # 字典格式存数据库要转str
        Apis.add_apis(
            form.api_name.data, form.request_method.data, path, str(headers), str(data),
            asserts, str(a['result']))
        result = ApiTestSuccess()
        result.content = a
        return result
    else:
        result = ApiTestFail()
        result.content = a
        return result


# 接口查询
@api.route('/examine_api', methods=['POST'])
@auth.login_required
def examine_api():
    api_name = request.json.get('api_name')
    if not api_name:
        apis = Apis.query.filter_by().all()
    else:
        apis = Apis.query.filter_by(api_name=api_name)
    api = [api for api in apis]
    return jsonify(api)


# 场景录入
@api.route('/scene_record', methods=['POST'])
@auth.login_required
def scene_record():
    form = SceneForm().validate_for_api()
    api_name_list = form.api_name_list.data
    scene_name = form.scene_name.data
    # 场景表记录场景名称和该场景下的接口
    Scene.add_scene(scene_name, str(api_name_list))
    # 在接口场景表写入 接口id 和场景id
    print(api_name_list)
    if isinstance(api_name_list,str):
        api_name_list=eval(api_name_list)
    for i in api_name_list:
        print(i)
        # 场景包含接口列表的顺序表示在场景下的运行顺序
        api_id = Apis.query.filter(Apis.api_name == i).first().id
        scene_id = Scene.query.filter(Scene.scene_name == scene_name).first().id
        print(api_id)
        ApisScene.add_apis_scene(scene_id, api_id, i, "", "", "", "", "", "")
    return Success()
@api.route('/get_scene_record', methods=['POST'])
@auth.login_required
def get_scene_record():
    ss= Scene.query.filter_by().all()
    s = [s for s in ss]
    return jsonify(s)

# # 查询接口脚本的录制顺序
# @api.route('/script_order', methods=['POST'])
# # @auth.login_required
# def script_order():
#     form = ApisSceneForm().validate_for_api()
#     scene_name = form.scene_name.data
#     scene = Scene.query.filter_by(scene_name=scene_name).first()
#     scene_api_list = eval(scene.api_name_list)
#     result = dict(api_count=len(scene_api_list), api_list=scene_api_list)
#     results = Success()
#     results.content = result
#     return results


# 脚本录制
@api.route('/scene_script', methods=['POST'])
@auth.login_required
def scene_script():
    api_result = {}
    form = SceneScriptForm().validate_for_api()
    scene_name = form.scene_name.data
    script_data = form.script_data.data
    # 判断下脚本数量和场景脚本数量是否一致

    print(len(eval(Scene.query.filter_by(scene_name=scene_name).first().api_name_list)))
    if len(script_data) == len(eval(Scene.query.filter_by(scene_name=scene_name).first().api_name_list)):
        for i in script_data:
            path = i['path']
            api_name = i['api_name']
            ip = Config.query.filter_by(use=1).first().ip
            request_method = i['request_method']
            headers = Apis.query.filter_by(path=i['path']).first().headers
            request_parameter = i['request_parameter']
            is_depend = i['is_depend']
            depend_api_name = i['depend_api_name']
            asserts_expression = i['asserts_expression']
            depend_replace = i['depend_replace']
            if is_depend == 1:
                for k, v in depend_replace.items():
                    try:
                        # print(api_result[depend_api_name])
                        request_parameter[k] = eval(v)
                    except KeyError as err:
                        return jsonify({"msg": "索引{}不存在".format(err)})
            jie_guo = http(path, request_parameter, ip, headers, request_method, asserts_expression, api_name)
            if jie_guo['ex_code'] == 999:
                return jie_guo
            api_result[api_name] = jie_guo
            # 根据api_name来补全之前录的接口场景脚本
            scene_id = Scene.query.filter(Scene.scene_name == scene_name).first().id
            api_scene = ApisScene.query.filter(ApisScene.scene_id == scene_id, ApisScene.api_name == api_name).first()
            if api_scene == None:
                return jsonify({"msg": "接口名称未查到，检测接口名称"})
            # 写入数据库的数据类型不能为字典，列表
            api_scene.path = path
            api_scene.request_method = request_method
            api_scene.request_parameter = str(i['request_parameter'])
            api_scene.is_depend = is_depend
            api_scene.depend_api_name = depend_api_name
            api_scene.asserts_expression = asserts_expression
            api_scene.depend_replace = str(depend_replace)
            db.session.commit()
        return Success()
    else:
        return jsonify({"code": "999", "msg": "脚本数量不对"})

@api.route('/examine_script', methods=['POST'])
@auth.login_required
def examine_script():
    ss = ApisScene.query.filter_by().all()
    s = [s for s in ss]
    return jsonify(s)
@api.route('/examine_script_log', methods=['POST'])
@auth.login_required
def examine_script_log():
    ss = ApiExecutiveLogging.query.filter_by().all()
    s = [s for s in ss]
    return jsonify(s)
# 脚本使用
@api.route('/script_use', methods=['POST'])
@auth.login_required
def script_use():
    scene_name = request.json.get('scene_name')
    api_result = {}
    scene_id = Scene.query.filter_by(scene_name=scene_name).first().id
    scene_list = ApisScene.query.filter_by(scene_id=scene_id).all()
    for i in scene_list:
        path = i.path
        api_name = i.api_name
        api_id = i.api_id
        ip = Config.query.filter_by(use=1).first().ip
        request_method = i.request_method
        headers = Apis.query.filter_by(path=i['path']).first().headers
        request_parameter = i.request_parameter
        is_depend = i.is_depend
        depend_api_name = i.depend_api_name
        asserts_expression = i.asserts_expression
        depend_replace = i.depend_replace
        # print(eval(depend_replace))
        if is_depend == 1:
            request_parameter = eval(request_parameter)
            for k, v in eval((depend_replace)).items():
                try:
                    request_parameter[k] = eval(v)
                except KeyError as err:
                    return jsonify({"msg": "索引{}不存在".format(err)})

        jie_guo = http(path, request_parameter, ip, headers, request_method, asserts_expression, api_name)
        api_result[api_name] = jie_guo
        ApiExecutiveLogging.add_log(scene_id, scene_name, api_id, api_name, ip, path, headers, request_method,
                                    depend_replace, str(request_parameter), depend_api_name, 1,
                                    asserts_expression, str(jie_guo))
    return Success()


def http(path, data, ip, headers, method, asserts, api_name=''):
    url = ip + path
    if isinstance(headers, str):
        headers = eval(headers)
    if isinstance(data, str):
        data = eval(data)
    if data != '':
        result = requests.request(method=method, url=url, headers=headers, data=json.dumps(data))
    else:
        result = requests.request(method=method, url=url, headers=headers)
    if eval(asserts):
        return {'ex_code': 0, 'err_msg': '{}断言成功'.format(api_name), 'result': result.json()}
    else:
            return {'ex_code': 999, 'err_msg': '{}断言失败'.format(api_name), 'err_result': result.json()}
